﻿using System;
using System.IO;
using System.ServiceModel.Channels;
using TIBCO.Rendezvous;
using Message = System.ServiceModel.Channels.Message;

namespace Tibco.ServiceModel
{
    internal class TibcoRequestContext : RequestContext
    {
        private Message _message;
        private MessageEncoder m_encoder;
        TIBCO.Rendezvous.Message requestMsg;
        TimeSpan timeout;
        NetTransport _transport;
        private Action<Message, TimeSpan> _replyMethod;

        internal TibcoRequestContext(NetTransport transport, MessageEncoder encoder, Message requestMessage, TIBCO.Rendezvous.Message requestMsg, TimeSpan timeout)
        {
            this._transport = transport;
            this.m_encoder = encoder;
            this._message = requestMessage;
            this.requestMsg = requestMsg;
            this.timeout = timeout;

            _replyMethod = new Action<Message, TimeSpan>(this.Reply);
        }

        public override Message RequestMessage => _message;


        public override void Abort()
        {            
        }

        public override IAsyncResult BeginReply(Message message, AsyncCallback callback, object state)
        {
            return this.BeginReply(message, timeout, callback, state);
        }

        public override IAsyncResult BeginReply(Message message, TimeSpan timeout, AsyncCallback callback, object state)
        {
            return _replyMethod.BeginInvoke(message, timeout, callback, state);
        }

        public override void Close()
        {
            Close(timeout);
        }

        public override void Close(TimeSpan timeout)
        {
        }

        public override void EndReply(IAsyncResult result)
        {
            _replyMethod.EndInvoke(result);
        }

        public override void Reply(Message message)
        {
            this.Reply(message, timeout);
        }

        public override void Reply(Message message, TimeSpan timeout)
        {
            if (message != null)
            {
                try
                {
                    byte[] array = null;
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        this.m_encoder.WriteMessage(message, memoryStream);
                        array = memoryStream.ToArray();
                    }

                    var s = System.Text.Encoding.UTF8.GetString(array, 0, array.Length);
                    var msg = new TIBCO.Rendezvous.Message();
                    msg.SendSubject = requestMsg.ReplySubject;
                    msg.AddField("DATA", s);
                    this._transport.SendReply(msg, requestMsg);

                    Debug.Out("TibcoRequestContext.Reply()", s);
                }
                catch(Exception ex)
                {
                    Debug.Out("TibcoRequestContext.Reply() Exception", ex.Message);
                }
            }
        }
    }
}
